package net.maku.framework.common.utils;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

public class ApiSignUtils {

    @Component
    static class Config {

        private static String SCHEME_ID;
        private static String APP_ID;
        private static String APP_SECRET;
        private static String PATH;
        private static String API_PATH;

        @Value("${check-content.path}")
        public void setPath(String path) {
            this.PATH = path;
        }

        @Value("${check-content.api-path}")
        public void setApiPath(String apiPath) {
            this.API_PATH = apiPath;
        }

        @Value("${check-content.app-id}")
        public void setAppId(String appId) {
            this.APP_ID = appId;
        }

        @Value("${check-content.app-secret}")
        public void setAppSecret(String appSecret) {
            this.APP_SECRET = appSecret;
        }

        @Value("${check-content.scheme-id}")
        public void setSchemeId(String schemeId) {
            this.SCHEME_ID = schemeId;
        }

    }

    // 发送 POST 请求并签名
    public static String doPost(TreeMap<String, String> queryMap, String content) throws Exception {
        // 获取当前时间戳（毫秒）
        long signTimestamp = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();

        // 生成随机数
        String nonce = UUID.randomUUID().toString().replaceAll("-", "");

        // 拼接签名字符串
        StringBuilder signParamBuilder = new StringBuilder();
        signParamBuilder.append(Config.API_PATH);  // 请求路径

        // 如果有查询参数，拼接到路径后
        String queryStr = createQueryParams(queryMap);
        if (queryStr != null && !"".equals(queryStr)) {
            signParamBuilder.append("?").append(queryStr);
        }

        Map<String, Object> body = new HashMap<>();
        body.put("content", content);
        body.put("schemeId", Config.SCHEME_ID);

        // 将请求体转换为 JSON 字符串
        String bodyJson = JSON.toJSONString(body);

        // 拼接请求体
        signParamBuilder.append(bodyJson);

        // 拼接时间戳和随机数
        signParamBuilder.append(signTimestamp);
        signParamBuilder.append(nonce);

        // 打印拼接的签名字符串，便于调试
        System.out.println("签名拼接字符串: " + signParamBuilder.toString());

        // 生成签名并进行 Base64 编码
        String sign = createBase64EncodeSign(signParamBuilder.toString(), Config.APP_SECRET);

        // URL 编码签名
        sign = URLEncoder.encode(sign, "UTF-8");

        // 打印调试信息
        System.out.println("请求URL: " + Config.PATH + Config.API_PATH);
        System.out.println("请求体: " + bodyJson);
        System.out.println("签名: " + sign);
        System.out.println("时间戳: " + signTimestamp);
        System.out.println("随机数: " + nonce);

        // 发送 POST 请求
        String url = Config.PATH + Config.API_PATH;
        return sendPostRequest(url, bodyJson, sign, signTimestamp, nonce);
    }

    // 发送实际的 POST 请求
    private static String  sendPostRequest(String url, String jsonStr, String sign, long signTimestamp, String nonce) {
        StringBuilder result = new StringBuilder();
        OutputStreamWriter out = null;
        BufferedReader in = null;
        HttpURLConnection conn = null;

        try {
            // 创建 HTTP 连接
            java.net.URL apiUrl = new URL(url);
            conn = (HttpURLConnection) apiUrl.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(10 * 60 * 1000);
            conn.setReadTimeout(5 * 60 * 1000);
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            conn.setRequestProperty("apiSign-appId", Config.APP_ID);
            conn.setRequestProperty("apiSign-timestamp", String.valueOf(signTimestamp));
            conn.setRequestProperty("apiSign-nonce", nonce);
            conn.setRequestProperty("apiSign-sign", sign);

            // 发送请求体
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            out.write(jsonStr);
            out.flush();

            // 处理响应
            if (200 == conn.getResponseCode()) {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                    //System.out.println(result);
                }
            } else {
                System.out.println("ResponseCode is an error code:" + conn.getResponseCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) out.close();
                if (in != null) in.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }

        return result.toString();
    }

    // 拼接查询参数
    private static String createQueryParams(TreeMap<String, String> queryMap) {
        StringBuilder strBuilder = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : queryMap.entrySet()) {
            if (entry.getValue() != null) {
                if (first) {
                    first = false;
                } else {
                    strBuilder.append("&");
                }
                strBuilder.append(entry.getKey()).append("=").append(entry.getValue());
            }
        }
        return strBuilder.toString();
    }

    // 生成签名并进行 Base64 编码
    private static String createBase64EncodeSign(String signUrl, String appSecret) throws Exception {
        byte[] signByte = hmacSHA1Encrypt(signUrl, appSecret);
        return Base64.getEncoder().encodeToString(signByte);
    }

    // HMAC-SHA1 加密
    private static byte[] hmacSHA1Encrypt(String encryptText, String encryptKey) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String MAC_NAME = "HmacSHA1";
        String ENCODING = "UTF-8";
        byte[] keyData = encryptKey.getBytes(ENCODING);
        Mac mac = Mac.getInstance(MAC_NAME);
        SecretKey secretKey = new SecretKeySpec(keyData, MAC_NAME);
        mac.init(secretKey);
        byte[] textData = encryptText.getBytes(ENCODING);
        return mac.doFinal(textData);
    }

    // 手动构建 JSON 字符串
    public static String buildJsonString(Map<String, Object> body) {
        StringBuilder jsonBuilder = new StringBuilder();
        jsonBuilder.append("{");

        for (Map.Entry<String, Object> entry : body.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            jsonBuilder.append("\"").append(key).append("\":");

            if (value instanceof String) {
                jsonBuilder.append("\"").append(value).append("\"");
            } else {
                jsonBuilder.append(value);
            }

            jsonBuilder.append(",");
        }

        // 删除最后一个多余的逗号
        if (jsonBuilder.length() > 1) {
            jsonBuilder.deleteCharAt(jsonBuilder.length() - 1);
        }

        jsonBuilder.append("}");
        return jsonBuilder.toString();
    }
}
